package vip.xiaonuo.modular.reactor;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.Reactor;
import reactor.event.Event;
import reactor.function.Consumer;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.facedoor.modular.topic.EventTopic;
import vip.xiaonuo.facedoor.modular.visitor.entity.Visitor;
import vip.xiaonuo.facedoor.modular.visitor.service.VisitorService;
import vip.xiaonuo.modular.remoteapi.stairs.RemoteStairsConstant;
import vip.xiaonuo.modular.sync.DeviceEvent;
import vip.xiaonuo.modular.ybuildingmemberrl.entity.YBuildingMemberRl;
import vip.xiaonuo.modular.ybuildingmemberrl.mapper.YBuildingMemberRlMapper;
import vip.xiaonuo.modular.ybuildingmemberrl.param.YBuildingMemberRlParam;
import vip.xiaonuo.modular.ybuildingvisitorrl.entity.YBuildingVisitorRl;
import vip.xiaonuo.modular.ybuildingvisitorrl.mapper.YBuildingVisitorRlMapper;
import vip.xiaonuo.modular.ybuildingvisitorrl.param.YBuildingVisitorRlParam;
import vip.xiaonuo.modular.ydeviceevent.entity.YDeviceEvent;
import vip.xiaonuo.modular.ydeviceevent.mapper.YDeviceEventMapper;
import vip.xiaonuo.modular.yelevatordevice.entity.YElevatorDevice;
import vip.xiaonuo.modular.yelevatordevice.service.YElevatorDeviceService;
import vip.xiaonuo.sys.modular.org.entity.SysOrg;
import vip.xiaonuo.sys.modular.org.service.SysOrgService;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import static reactor.event.selector.Selectors.$;

/**
 * 访客机新增访客 监听 门禁设备增加
 */
@Service
@Slf4j
public class StatisVisitorDeviceAddListener implements Consumer<Event<Long>>, InitializingBean {

    @Autowired
    private Reactor reactor;

    @Autowired
    private VisitorService visitorService;

    @Autowired
    private SysOrgService sysOrgService;

    @Resource
    private YBuildingVisitorRlMapper buildingVisitorRlMapper;

    @Autowired
    private YElevatorDeviceService elevatorDeviceService;

    @Resource
    private YDeviceEventMapper deviceEventMapper;

    @Autowired
    private MemberUserService memberService;

    @Resource
    private YBuildingMemberRlMapper yBuildingMemberRlMapper;

    @Override
    public void accept(Event<Long> event) {
        Visitor visitor = visitorService.getById(event.getData());
        if (visitor == null) {
            log.error("访客不存在【{}】", event.getData());
            return;
        }
        if (visitor.getUpToStaris() != null && visitor.getUpToStaris()) {
            log.error("【{}】已经下发到电梯中不进行二次下发!", visitor);
            return;
        }
        log.info("访客机新增访客 监听 梯控设备增加【{}】", visitor.getName());
        SysOrg sysOrg = sysOrgService.getById(visitor.getCompanyId());
        if (sysOrg == null) {
            throw new ServiceException(500, "找不到被访人公司");
        }

        MemberUser invitorMember = null;
        // 如果邀请人不为null  则使用邀请人的组织
        if (visitor.getInviterId()!=null) {
            invitorMember = memberService.getById(visitor.getInviterId());
        }

        // 如果邀请人不为null  则使用邀请人的组织
        log.info("访客机新增访客 监听 梯控设备增加【{}】", visitor.getName());
        if (invitorMember != null) {
            copyMemberDevice(visitor, invitorMember);
            return;
        }
        copyOrgDevice(visitor, sysOrg);
    }

    private void copyOrgDevice(Visitor visitor, SysOrg sysOrg) {
        AtomicReference<Boolean> updateToStairs = new AtomicReference<>(Boolean.FALSE);
        List<YElevatorDevice> yElevatorDevices = elevatorDeviceService.list(new LambdaQueryWrapper<YElevatorDevice>().eq(YElevatorDevice::getBuildingId, sysOrg.getBuildingId()));
        List<YBuildingVisitorRl> visitorRls = buildingVisitorRlMapper.findList(new YBuildingVisitorRlParam().setVisitorId(visitor.getId()));

        // 未下发到电梯而且 【卡号不为null】，并且关联表中有数据，证明二维码下发过一次,所以这是第一次读卡操作需下发到梯控
        if (CollectionUtil.isNotEmpty(visitorRls) && !visitor.getUpToStaris() && visitor.getIcCard()!=null&&StringUtils.isNotBlank(visitor.getIcCard())) {
            for (YBuildingVisitorRl visitorRl : visitorRls) {
                visitorRl.setDeviceSyncStatus(RemoteStairsConstant.DeviceSyncStatus.ADD);
                buildingVisitorRlMapper.updateById(visitorRl);

                YElevatorDevice elevatorDevice = elevatorDeviceService.getById(visitorRl.getDeviceId());
                // 保存事件
                YDeviceEvent deviceEvent = new YDeviceEvent();
                deviceEvent.setDeviceNo(elevatorDevice.getDeviceNo());
                deviceEvent.setStatus(DeviceEvent.NEW);
                deviceEvent.setSysType(2);
                deviceEvent.setCreateDate(new Date());
                deviceEvent.setBody(visitorRl.getId().toString());
                deviceEvent.setType(RemoteStairsConstant.RequestCmd.ADD_PERSON);
                deviceEventMapper.insert(deviceEvent);
            }
            visitor.setUpToStaris(Boolean.TRUE);
            visitorService.updateById(visitor);
            // 未下发到电梯 【卡号为null】，并且关联表中有数据，证明二维码下发过一次,所以这里只是打印二维码
        } else if (CollectionUtil.isNotEmpty(visitorRls) && !visitor.getUpToStaris() && StringUtils.isBlank(visitor.getIcCard())) {
            log.info("【{}】只打印二维码不添加人员", visitor.getName());
            // 首次下发
        } else {
            yElevatorDevices.forEach(yElevatorDevice -> {
                // 增加关联关系
                YBuildingVisitorRl yBuildingVisitorRl = new YBuildingVisitorRl();
                yBuildingVisitorRl.setDeviceRole("0");
                yBuildingVisitorRl.setLiveFloor(sysOrg.getLiveFloor());
                yBuildingVisitorRl.setHandFloor(sysOrg.getHandFloor());
                yBuildingVisitorRl.setDeviceId(yElevatorDevice.getId());
                yBuildingVisitorRl.setVisitorId(visitor.getId());
                yBuildingVisitorRl.setBuildingId(sysOrg.getBuildingId());
                if (StringUtils.isNotBlank(visitor.getIcCard())) {
                    yBuildingVisitorRl.setDeviceSyncStatus(RemoteStairsConstant.DeviceSyncStatus.ADD);
                } else {
                    yBuildingVisitorRl.setDeviceSyncStatus(RemoteStairsConstant.DeviceSyncStatus.SYNC_SUCCESS);
                }
                buildingVisitorRlMapper.insert(yBuildingVisitorRl);

                // 区分二维码 还是读卡操作
                if (StringUtils.isNotBlank(visitor.getIcCard())) {
                    // 保存事件
                    updateToStairs.set(Boolean.TRUE);
                    YDeviceEvent deviceEvent = new YDeviceEvent();
                    deviceEvent.setDeviceNo(yElevatorDevice.getDeviceNo());
                    deviceEvent.setStatus(DeviceEvent.NEW);
                    deviceEvent.setSysType(2);
                    deviceEvent.setCreateDate(new Date());
                    deviceEvent.setBody(yBuildingVisitorRl.getId().toString());
                    deviceEvent.setType(RemoteStairsConstant.RequestCmd.ADD_PERSON);
                    deviceEventMapper.insert(deviceEvent);
                }
            });
            // 是否已经下发到电梯中
            if (updateToStairs.get()) {
                visitor.setUpToStaris(updateToStairs.get());
                visitorService.updateById(visitor);
            }
        }
    }

    private void copyMemberDevice(Visitor visitor, MemberUser invitorMember) {
        AtomicReference<Boolean> updateToStairs = new AtomicReference<>(Boolean.FALSE);

        List<YBuildingVisitorRl> visitorRls = buildingVisitorRlMapper.findList(new YBuildingVisitorRlParam().setVisitorId(visitor.getId()));

        // 未下发到电梯而且 【卡号不为null】，并且关联表中有数据，证明二维码下发过一次,所以这是第一次读卡操作需下发到梯控
        if (CollectionUtil.isNotEmpty(visitorRls) && visitor.getIcCard()!=null&&!visitor.getUpToStaris()
                && StringUtils.isNotBlank(visitor.getIcCard())) {
            for (YBuildingVisitorRl visitorRl : visitorRls) {
                visitorRl.setDeviceSyncStatus(RemoteStairsConstant.DeviceSyncStatus.ADD);
                buildingVisitorRlMapper.updateById(visitorRl);

                YElevatorDevice elevatorDevice = elevatorDeviceService.getById(visitorRl.getDeviceId());
                // 保存事件
                YDeviceEvent deviceEvent = new YDeviceEvent();
                deviceEvent.setDeviceNo(elevatorDevice.getDeviceNo());
                deviceEvent.setStatus(DeviceEvent.NEW);
                deviceEvent.setSysType(2);
                deviceEvent.setCreateDate(new Date());
                deviceEvent.setBody(visitorRl.getId().toString());
                deviceEvent.setType(RemoteStairsConstant.RequestCmd.ADD_PERSON);
                deviceEventMapper.insert(deviceEvent);
            }
            visitor.setUpToStaris(Boolean.TRUE);
            visitorService.updateById(visitor);
            // 未下发到电梯 【卡号为null】，并且关联表中有数据，证明二维码下发过一次,所以这里只是打印二维码
        } else if (CollectionUtil.isNotEmpty(visitorRls) && !visitor.getUpToStaris() && StringUtils.isBlank(visitor.getIcCard())) {
            log.info("【{}】只打印二维码不添加人员", visitor.getName());
            // 首次下发
        } else {
            // 首次添加到梯控中
            List<YBuildingMemberRl> buildingMemberRls = yBuildingMemberRlMapper.findList(new YBuildingMemberRlParam().setMemberId(invitorMember.getId()));
            for (YBuildingMemberRl buildingMemberRl : buildingMemberRls) {
                Long deviceId = buildingMemberRl.getDeviceId();
                YElevatorDevice byId = elevatorDeviceService.getById(deviceId);
                if (byId == null) {
                    log.error("找不到设备id【【{}】", deviceId);
                    continue;
                }
                // 不允许复制管理员权限
                if (buildingMemberRl.getDeviceRole().equals("0")) {
                    YBuildingVisitorRl saveBean = new YBuildingVisitorRl();
                    BeanUtils.copyProperties(buildingMemberRl, saveBean);
                    if (StringUtils.isNotBlank(visitor.getIcCard())) {
                        saveBean.setDeviceSyncStatus(RemoteStairsConstant.DeviceSyncStatus.ADD);
                        // 区分二维码还是读卡
                    } else {
                        saveBean.setDeviceSyncStatus(RemoteStairsConstant.DeviceSyncStatus.SYNC_SUCCESS);
                    }
                    saveBean.setId(null);
                    saveBean.setVisitorId(visitor.getId());
                    buildingVisitorRlMapper.insert(saveBean);
                    // 区分二维码还是读卡
                    if (StringUtils.isNotBlank(visitor.getIcCard())) {
                        // 保存事件
                        updateToStairs.set(Boolean.TRUE);
                        // 保存事件
                        YDeviceEvent deviceEvent = new YDeviceEvent();
                        deviceEvent.setDeviceNo(byId.getDeviceNo());
                        deviceEvent.setStatus(DeviceEvent.NEW);
                        deviceEvent.setSysType(2);
                        deviceEvent.setCreateDate(new Date());
                        deviceEvent.setBody(saveBean.getId().toString());
                        deviceEvent.setType(RemoteStairsConstant.RequestCmd.ADD_PERSON);
                        deviceEventMapper.insert(deviceEvent);
                    }
                }
            }
            // 已经下发到电梯中 不进行二次下发
            if (updateToStairs.get()) {
                visitor.setUpToStaris(updateToStairs.get());
                visitorService.updateById(visitor);
            }
        }


    }

    @Override
    public void afterPropertiesSet() throws Exception {
        reactor.on($(EventTopic.VISITOR_DEVICE_ADD), this);
    }
}
